using System;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Actions;
using DotNetNuke.Security;

namespace HeroldIT.Dnn.Modules.News.Views
{
    public class NewsList : ViewBase<NewsListContainer>, INewsListSettingsProvider, IActionable
    {
        #region control fields

        protected Repeater rptNewsEntries;
        protected Panel pnlSearch;
        protected ITextControl txtNewsSearch;
        protected Panel pnlPagerTop;
        protected Panel pnlPagerBottom;
        protected TextBox txtFrom;
        protected TextBox txtUntil;
        protected Control btnPagerEarlierTop;
        protected Control btnPagerLaterTop;
        protected Control btnPagerEarlierBottom;
        protected Control btnPagerLaterBottom;

        #endregion

        #region properties

        protected bool ShowCurrentItems
        {
            get { return this.GetShowCurrentItems() || !this.GetShowArchivedItems(); }
        }

        protected bool ShowArchivedItems
        {
            get { return this.GetShowArchivedItems(); }
        }

        protected int MaxCurrentItems
        {
            get
            {
                if (this.HasCoreModule)
                    return this.Controller.GetMaxCurrentItems();

                return 15;
            }
        }

        protected int MaxVisibleItems
        {
            get { return this.GetMaxVisibleItems(); }
        }

        private UrlController urlController;

        protected UrlController UrlController
        {
            get
            {
                if (null == this.urlController)
                {
                    this.urlController = new UrlController();
                }
                return this.urlController;
            }
        }

        private PagedList<NewsEntry> newsEntries;

        protected PagedList<NewsEntry> NewsEntries
        {
            get
            {
                if (null == this.newsEntries)
                {
                    this.newsEntries = this.ReadNewsEntries(0);
                }
                return this.newsEntries;
            }
        }

        public ModuleActionCollection ModuleActions
        {
            get
            {
                if (this.HasCoreModule)
                {
                    ModuleActionCollection actions = new ModuleActionCollection
                                                         {
                                                             {
                                                                 this.ModuleBase.GetNextActionID(),
                                                                 this.GetString("AddContent.Action"), "AddContent.Action",
                                                                 "", "", this.ModuleBase.EditUrl(), false,
                                                                 SecurityAccessLevel.Edit, true, false
                                                                 }
                                                         };
                    return actions;
                }
                return new ModuleActionCollection();
            }
        }

        protected int CurrentPage
        {
            get
            {
                object newsPage = this.ViewState["newspage"];
                if (null == newsPage || !(newsPage is int))
                {
                    this.CurrentPage = 0;
                    newsPage = 0;
                }
                return (int)newsPage;
            }
            set
            {
                this.ViewState["newspage"] = value;
            }
        }

        #endregion

        #region page lifecycle

        protected override void OnLoad(EventArgs e)
        {
            if (this.AutoBind && null != this.NewsEntries && null != this.rptNewsEntries)
            {
                this.rptNewsEntries.DataSource = this.NewsEntries;
                this.rptNewsEntries.DataBind();
            }
            if (this.ShowArchivedItems)
            {
                if (null != this.pnlSearch)
                {
                    this.pnlSearch.Visible = true;
                }
                if (null != this.pnlPagerTop)
                {
                    this.pnlPagerTop.Visible = true;
                }
                if (null != this.pnlPagerBottom)
                {
                    this.pnlPagerBottom.Visible = true;
                }
                this.BindResults();
            }
            else
            {
                if (null != this.pnlSearch)
                {
                    this.pnlSearch.Visible = false;
                }
                if (null != this.pnlPagerTop)
                {
                    this.pnlPagerTop.Visible = false;
                }
                if (null != this.pnlPagerBottom)
                {
                    this.pnlPagerBottom.Visible = false;
                }
            }
            base.OnLoad(e);

            if (this.GetAddFeedToPage())
            {
                this.ModuleConfiguration.AddFeedToPage(this.Page);
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (!this.HasCoreModule)
            {
                if (this.IsEditable)
                {
                    string noCoreModule = this.GetString("litNoCoreModule.Text");
                    if (String.IsNullOrEmpty(noCoreModule))
                    {
                        noCoreModule =
                            "No core module has been configured for this module. Please configure it before proceeding.";
                    }
                    writer.Write("<a href=\"{0}\">{1}</a>",
                                 Globals.NavigateURL(this.ModuleConfiguration.TabID, "Module",
                                                     new[] { "ModuleId=" + this.ModuleConfiguration.ModuleID }),
                                 noCoreModule);
                }
            }
            else
            {
                base.Render(writer);
            }
        }

        #endregion

        #region event handlers

        protected void btnDeleteEntry_Command(object sender, CommandEventArgs e)
        {
            int id;
            if (int.TryParse(e.CommandArgument as string, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
            {
                if (id > 0)
                {
                    this.DeleteNewsEntry(id);
                }
            }
        }

        protected void btnNewsSearch_Click(object sender, EventArgs e)
        {
            this.CurrentPage = 0;
            this.BindResults();
        }

        protected void btnPagerLater_Click(object sender, EventArgs e)
        {
            this.CurrentPage -= 1;
            this.BindResults();
        }

        protected void btnPagerEarlier_Click(object sender, EventArgs e)
        {
            this.CurrentPage += 1;
            this.BindResults();
        }

        #endregion

        #region methods

        protected void BindResults()
        {
            if (null != this.rptNewsEntries)
            {
                DateTime? from = null;
                DateTime? until = null;
                if (this.IsPostBack)
                {
                    DateTime parsed;
                    if (null != this.txtFrom && DateTime.TryParse(this.txtFrom.Text, CultureInfo.CurrentUICulture, DateTimeStyles.AssumeLocal,
                                          out parsed))
                    {
                        from = parsed.Date;
                    }
                    if (null != this.txtUntil && DateTime.TryParse(this.txtUntil.Text, CultureInfo.CurrentUICulture, DateTimeStyles.AssumeLocal,
                                          out parsed))
                    {
                        until = parsed.Date.AddDays(1).AddMilliseconds(-1);
                    }
                }

                PagedList<NewsEntry> entries =
                    this.FindNewsEntries(null != this.txtNewsSearch ? this.txtNewsSearch.Text : null, from, until, this.CurrentPage);

                this.rptNewsEntries.DataSource = entries;
                this.rptNewsEntries.DataBind();

                if (entries.TotalCount > this.MaxVisibleItems)
                {
                    if (null != this.pnlPagerTop)
                    {
                        this.pnlPagerTop.Visible = true;
                    }
                    if (null != this.pnlPagerBottom)
                    {
                        this.pnlPagerBottom.Visible = true;
                    }
                    if (null != this.btnPagerLaterTop)
                    {
                        this.btnPagerLaterTop.Visible = this.CurrentPage > 0;
                    }
                    if (null != this.btnPagerLaterBottom)
                    {
                        this.btnPagerLaterBottom.Visible = this.CurrentPage > 0;
                    }
                    if (null != this.btnPagerEarlierTop)
                    {
                        this.btnPagerEarlierTop.Visible = (this.CurrentPage + 1) * this.MaxVisibleItems < entries.TotalCount;
                    }
                    if (null != this.btnPagerEarlierBottom)
                    {
                        this.btnPagerEarlierBottom.Visible = (this.CurrentPage + 1) * this.MaxVisibleItems
                                                             < entries.TotalCount;
                    }
                }
                else
                {
                    if (null != this.pnlPagerTop)
                    {
                        this.pnlPagerTop.Visible = false;
                    }
                    if (null != this.pnlPagerBottom)
                    {
                        this.pnlPagerBottom.Visible = false;
                    }
                }
            }
        }

        protected UrlInfo GetUrlInfo(NewsEntry entry)
        {
            return this.UrlController.GetUrl(this.PortalSettings.PortalId, entry.Details[0].DetailUrl);
        }

        protected UrlTrackingInfo GetUrlTrackingInfo(NewsEntry entry)
        {
            return this.UrlController.GetUrlTracking(this.PortalSettings.PortalId, entry.Details[0].DetailUrl,
                                                     this.ModuleConfiguration.ModuleID);
        }

        protected PagingInfo CalculatePagingInfo(int page)
        {
            int skip = page * this.MaxVisibleItems;
            if (!this.ShowCurrentItems)
            {
                skip += this.MaxCurrentItems;
            }
            int take = this.MaxVisibleItems;
            if (!this.ShowArchivedItems && skip + take > this.MaxCurrentItems)
            {
                take = this.MaxCurrentItems - skip;
            }
            return new PagingInfo(skip, take);
        }

        protected PagedList<NewsEntry> ReadNewsEntries(int page)
        {
            if (this.HasCoreModule)
            {
                PagingInfo pagingInfo = this.CalculatePagingInfo(page);
                return this.Controller.ReadNewsEntries(CultureInfo.CurrentUICulture.Name,
                                                       pagingInfo.Skip, pagingInfo.Take, this.IsEditable);
            }
            return null;
        }

        protected PagedList<NewsEntry> FindNewsEntries(string filterText, int page)
        {
            if (this.HasCoreModule)
            {
                PagingInfo pagingInfo = this.CalculatePagingInfo(page);
                return this.Controller.FindNewsEntries(filterText, CultureInfo.CurrentUICulture.Name,
                                                       pagingInfo.Skip, pagingInfo.Take, this.IsEditable);
            }
            return null;
        }

        protected PagedList<NewsEntry> FindNewsEntries(string filterText, DateTime? from, DateTime? until, int page)
        {
            if (this.HasCoreModule)
            {
                PagingInfo pagingInfo = this.CalculatePagingInfo(page);
                return this.Controller.FindNewsEntries(filterText, CultureInfo.CurrentUICulture.Name, from, until,
                                                       pagingInfo.Skip, pagingInfo.Take, this.IsEditable);
            }
            return null;
        }

        protected bool HasDetailView(NewsEntry entry)
        {
            return !String.IsNullOrEmpty(entry.Details[0].DetailUrl)
                   || !String.IsNullOrEmpty(entry.Details[0].DetailText);
        }

        protected string GenerateListUrl()
        {
            return this.Controller.GenerateListUrl();
        }

        protected string GenerateDetailUrl(NewsEntry entry)
        {
            string detailUrl = entry.Details[0].DetailUrl;
            if (!String.IsNullOrEmpty(detailUrl))
            {
                UrlTrackingInfo trackingInfo = this.GetUrlTrackingInfo(entry);
                return Globals.LinkClick(detailUrl, this.ModuleConfiguration.TabID, this.ModuleConfiguration.ModuleID,
                                         null == trackingInfo ? false : trackingInfo.TrackClicks);
            }
            return this.GenerateDetailUrl(entry.NewsEntryId);
        }

        protected string GenerateDetailUrl(int newsEntryId)
        {
            if (this.HasCoreModule)
            {
                return this.Controller.GenerateDetailUrl(newsEntryId);
            }
            return null;
        }

        protected string GenerateDetailUrlTarget(NewsEntry entry)
        {
            string detailUrl = entry.Details[0].DetailUrl;
            if (!String.IsNullOrEmpty(detailUrl))
            {
                UrlTrackingInfo trackingInfo = this.GetUrlTrackingInfo(entry);
                return null != trackingInfo && trackingInfo.NewWindow ? "_blank" : "_self";
            }
            return "_self";
        }

        protected string GenerateEditUrl(int newsEntryId)
        {
            return this.EditUrl("EntryId", newsEntryId.ToString(CultureInfo.InvariantCulture));
        }

        protected void DeleteNewsEntry(int newsEntryId)
        {
            if (this.HasCoreModule)
            {
                this.Controller.DeleteNewsEntry(newsEntryId);
                this.Response.Redirect(this.Controller.GenerateListUrl());
            }
        }

        #endregion

        #region helper classes

        protected class PagingInfo
        {
            public int Skip { get; private set; }
            public int Take { get; private set; }

            public PagingInfo(int skip, int take)
            {
                this.Skip = skip;
                this.Take = take;
            }
        }

        #endregion
    }
}
